import com.google.common.util.concurrent.RateLimiter;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;

/**
 * Created by wuwf on 17/7/10.
 * 令牌桶
 */
public class TokenBucket {
    private static final ConcurrentHashMap<String, RateLimiter> rateLimiter = new ConcurrentHashMap<String, RateLimiter>();

    private static int xianCount = 0;

    private static void createFlowLimitMap(String resource, double qps) {
        RateLimiter limiter = rateLimiter.get(resource);
        if (limiter == null) {
            limiter = RateLimiter.create(qps);
            rateLimiter.putIfAbsent(resource, limiter);
        }
//        limiter.setRate(qps);
    }

    private static synchronized boolean enter(String resource) {
        RateLimiter limiter = rateLimiter.get(resource);
        if (limiter == null) {
            return false;
        }
        if (limiter.acquire() <= 0) {
            System.out.println("---被限流" + xianCount++);
            return false;
        }

        return true;
    }

    public static void main(String[] args) {
        createFlowLimitMap(RESOURCE, 5);
        for (int i = 0; i < threadNum; i++) {
            new Thread(new UserRequest("iphone", 1, i)).start();
            countDownLatch.countDown();
        }

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(enterUsers.size());
    }

    private static String RESOURCE = "iphone";
    /**
     * 并发量
     */
    private static int threadNum = 200;

    private static List<Integer> enterUsers = new ArrayList<Integer>();
    /*当创建 CountDownLatch 对象时，对象使用构造函数的参数来初始化内部计数器。每次调用 countDown() 方法,
     CountDownLatch 对象内部计数器减一。当内部计数器达到0时， CountDownLatch 对象唤醒全部使用 await() 方法睡眠的线程们。*/
    private static CountDownLatch countDownLatch = new CountDownLatch(threadNum);
    private static class UserRequest implements Runnable {

        private String code;
        private int buyCount;
        private int userId;

        public UserRequest(String code, int buyCount, int userId) {
            this.code = code;
            this.buyCount = buyCount;
            this.userId = userId;
        }

        public void run() {
            try {
                //让线程等待，等200个线程创建完一起执行
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (enter(RESOURCE)) {
                enterUsers.add(userId);
            }
        }
    }

}
